﻿#region Development Information
//====================================================== 
// LoggerUtility Class

//====================================================== 

// Created By : Kunal Uppal

// Created Date : 10th January, 2011

// Purpose : Logs Messages and exception in the file, database, email, XML, event based on the policy set
//           in the web.config
// Description : 
// Modified By : Kunal Uppal

// Modified Date : 22nd January, 2011

// Purpose : Added Method for logging messages asynhronously
// Description : 

// Modified By : Kunal Uppal

// Modified Date : 10th May' 2011

// Purpose : Added BlockingCollection variable to order the threads
// Description :
//====================================================== 
#endregion

# region references
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using System.Reflection;
using System.Threading;
using System.Collections.Concurrent;


#endregion

#region Implementation
namespace ALog.Logging
{
    /// <summary>
    /// Class For Logging Exceptions and messages in the the application
    /// </summary>
    public static class LoggerUtility
    {
        #region "Private Variables"
         private static BlockingCollection<Action> blockingCollection = new BlockingCollection<Action>();
        #endregion

        #region "StaticConstructor"
        /// <summary>
        /// Static constructor to initialize the Queue
        /// </summary>
       static LoggerUtility()
        {
          Console.WriteLine("Static Constructor Called");
                    
           //ThreadPool.QueueUserWorkItem(o => { Action op; while (logOperations.TryDequeue(out op)) op(); }); 
           //this is done to ensure that ThreadPool keep looking for some work item to queue
           //within that, Blocking operation will look if an item is added to the collection or not

            ThreadPool.QueueUserWorkItem(o => { while (true) { Thread.Sleep(2000); Console.WriteLine("Item will be searched for Queuing "); Action op; while (blockingCollection.TryTake(out op)) { op(); Console.WriteLine("Waiting for threads to Join"); } } }); 
        }

        #endregion

       #region "ExceptionLoggingMethods"

       /// <summary>
        /// Log Exception in the application with additional dictionary object 
        /// </summary>
        /// <param name="ex">Exception Object</param>
        /// <param name="lstOfObject">Dictionary collection. Add entities to log their properties</param>
        public static void LogException(Exception ex, List<Object> lst)
        {
            if (LogHandler.IsExceptionLoggingEnabled)
            {
                LogEntry logEntry = new LogEntry();
                logEntry.Message = "Additional Data Associated with exception";
                logEntry.Message += Environment.NewLine + SerializePropertyValue(lst);
                bool exceptionflag = ExceptionPolicy.HandleException(ex, "Default");
                Logger.Write(logEntry);
            }
        }
        /// <summary>
        /// Log Exception in the application
        /// </summary>
        /// <param name="ex">Exception Object</param>
        public static void LogException(Exception ex)
        {
            if (LogHandler.IsExceptionLoggingEnabled)
            {
                bool exceptionflag = ExceptionPolicy.HandleException(ex, "Default");
            }
        }
        /// <summary>
        /// Serializes the value of the properties of the class
        /// </summary>
        /// <param name="lst"></param>
        /// <returns></returns>
        private static string SerializePropertyValue(List<Object> lst)
        {
            //Log the collection associated with the message.
            Type typeInfo = null;
            StringBuilder messageString = null;
            //Enumerate and extract property of each object in the list
            foreach (Object objValue in lst)
            {
                typeInfo = objValue.GetType();
                PropertyInfo[] propertyCollection = typeInfo.GetProperties();
                messageString = new StringBuilder("Additional Data Associated with the exception");
                foreach (PropertyInfo propertyItem in propertyCollection)
                {
                    messageString.Append("Property Details:" + Environment.NewLine);
                    messageString.Append(propertyItem.Name + ":" + Convert.ToString(propertyItem.GetValue(objValue, null)) + Environment.NewLine);

                }


            }

            return messageString.ToString();
        }

        #endregion

        #region "MessageLoggingMethods
        /// <summary>
        /// Log Message in the application
        /// </summary>
        /// <param name="message">Messsage to be associated with the log</param>
        /// <param name="category">Value that should match with one of the category sources</param> 
        /// <param name="priority">Priority of the message</param>
        /// <param name="eventID">Event id of the message logged</param>
        /// <param name="typ">Trace event type</param>
        /// <param name="title">Title for the message logged</param>
        public static void LogMessages(Object message, int priority, int eventID, System.Diagnostics.TraceEventType typ, string title)
        {
            // LogEntry logEntry = new LogEntry(message, category, priority , eventID, System.Diagnostics.TraceEventType.Information, title, lst);
            LogEntry logEntry = new LogEntry { TimeStamp = DateTime.Now, Message = Convert.ToString(message), Priority = priority, EventId = eventID, Severity = typ, Title = title };
            Logger.Write(logEntry);

        }
        /// <summary>
        /// Log Message with additional Objects
        /// </summary>
        /// <param name="message">message to log</param>
        /// <param name="category">Category </param>
        /// <param name="priority">Priority of the message</param>
        /// <param name="eventID">Event id of the message</param>
        /// <param name="typ"></param>
        /// <param name="title">Title of the message</param>
        public static void LogMessages(Object message, int priority, int eventID, System.Diagnostics.TraceEventType typ, string title, List<object> lst)
        {

            string logMessage = Convert.ToString(message);

            if (lst != null && lst.Count > 0)
            {
                logMessage += SerializePropertyValue(lst);
            }
            LogMessages(logMessage, priority, eventID, typ, title);

        }

        /// <summary>
        /// Log Message with additional Objects Asynchronously
        /// </summary>
        /// <param name="message">message to log</param>
        /// <param name="category">Category </param>
        /// <param name="priority">Priority of the message</param>
        /// <param name="eventID">Event id of the message</param>
        /// <param name="typ"></param>
        /// <param name="title">Title of the message</param>
        public static void AsyncLogMessages(Object message, int priority, int eventID, System.Diagnostics.TraceEventType typ, string title, List<object> lst)
        {
            //ThreadPool.QueueUserWorkItem(o => LogMessages(message, priority, eventID, typ, title, lst));
           // logOperations.Enqueue(() => LogMessages(message, priority, eventID, typ, title, lst));
            blockingCollection.Add(() => LogMessages(message, priority, eventID, typ, title, lst));
        }



        /// <summary>
        /// Log Message in the application Asynchronously
        /// </summary>
        /// <param name="message">Messsage associated with the log item</param>
        /// <param name="category">Value that should match with one of the category sources</param> 
        /// <param name="priority">Priority of the message</param>
        /// <param name="eventID">Event id of the message logged</param>
        /// <param name="typ">Trace event type</param>
        /// <param name="title">Title for the message logged</param>
        public static void AsyncLogMessages(Object message, int priority, int eventID, System.Diagnostics.TraceEventType typ, string title)
        {
           // logOperations.Enqueue(() => LogMessages(message, priority, eventID, typ, title));
           // ThreadPool.QueueUserWorkItem(o => LogMessages(message, priority, eventID, typ, title));
            
            blockingCollection.Add(() => LogMessages(message, priority, eventID, typ, title));

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="message"></param>
        /// <param name="priority"></param>
        /// <param name="eventID"></param>
        /// <param name="typ"></param>
        /// <param name="title"></param>
        public static void LogMessageConcurrently(Object message, int priority, int eventID, System.Diagnostics.TraceEventType typ, string title)
        {
            //logOperations.Enqueue(() => LogMessages(message, priority, eventID, typ, title));
            
            blockingCollection.Add(() => LogMessages(message, priority, eventID, typ, title));
        }
       #endregion
   }
    
}
#endregion